package main

import "fmt"

type treeNode struct {
	value       int
	left, right *treeNode
}

/**
结构体方法的调用
*/
func (node treeNode) print() {
	fmt.Println(node.value)
}

/**
结构体的方法其实也可以写成跟正常方法一样，例如下图
*/
func prints(node treeNode) {
	fmt.Println(node.value)
}

/**
设置结构体中的值，检测结构体是值传递还是引用传递
在go语言中，所有的类型均是值传递
*/
func (node *treeNode) setValue(value int) {
	node.value = value
}

/**
结构体的遍历
*/
func (node *treeNode) traverser() {
	if node == nil {
		return
	}
	node.left.traverser()
	node.print()
	node.right.traverser()
}

func createTreeNode(value int) *treeNode {
	// 返回的是局部变量
	return &treeNode{value: value}
}

func main() {
	var root treeNode
	// {0 <nil> <nil>}
	fmt.Println(root)

	root = treeNode{value: 3}
	root.left = &treeNode{}
	root.right = &treeNode{5, nil, nil}
	root.right.left = new(treeNode)

	fmt.Println("create treeNode")
	// &{2 <nil> <nil>}
	fmt.Println(createTreeNode(2))

	// 结果体创建在堆上还是栈上  -> 不需要知道

	fmt.Println("结构体方法的调用")
	// 3
	root.print()

	fmt.Println("调用结构体方法的第二种方式")
	// 3
	prints(root)

	// 结构体是传值的还是值引用的?  在go语言中，所有的类型均是值传递
	fmt.Println("给结构体设置值")
	root.right.left.setValue(4)
	// 0  根据返回值可以得知结构体是值传递
	// 如果使用指针形式则返回4
	root.right.left.print()
	fmt.Println()

	// 结构体的灵活使用
	fmt.Println("结构体的灵活使用")
	// 3
	root.print()
	root.setValue(100)
	// 100 由于是指针的使用，所以会将地址传递进入，并非拷贝
	root.print()

	// 结构体的遍历
	fmt.Println("结构体的遍历")
	root.traverser()

	// 值接受者  VS  指针接受者  使用场景
	/**
	要改变内容必须使用指针接收者
	结构过大也考虑使用指针接收者
	一致性：如有指针接收者，最好都是指针接收者
	*/
}
